package org.JWCB.friend.manager;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.JWCB.common.core.constants.CacheConstants;
import org.JWCB.common.core.constants.QuestionConstants;
import org.JWCB.common.core.enums.ResultCode;
import org.JWCB.common.core.exception.ServiceException;
import org.JWCB.common.redis.service.RedisService;
import org.JWCB.friend.domain.question.entity.Question;
import org.JWCB.friend.domain.question.es.QuestionES;
import org.JWCB.friend.domain.question.vo.HotQuestionListVo;
import org.JWCB.friend.domain.user.entity.UserSubmit;
import org.JWCB.friend.elasticsearch.QuestionRepository;
import org.JWCB.friend.mapper.question.QuestionMapper;
import org.JWCB.friend.mapper.user.UserSubmitMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class QuestionCacheManager {

    @Autowired
    private RedisService redisService;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionRepository questionRepository;

    @Autowired
    private UserSubmitMapper userSubmitMapper;

    /**
     * 获取竞赛id列表的长度
     */
    public long getListSize() {
        return redisService.getListSize(CacheConstants.QUESTION_ID_LIST_KEY);
    }

    /**
     * 从数据库刷新缓存
     */
    public void refreshCache() {
        List<Question> questionList = questionMapper.selectList(new LambdaQueryWrapper<Question>()
                .select(Question::getQuestionId)
                .orderByDesc(Question::getCreateTime, Question::getQuestionId));

        if (questionList == null) {
            return;
        }
        List<Long> questionIds = questionList.stream().map(Question::getQuestionId).toList();
        redisService.rightPushAll(CacheConstants.QUESTION_ID_LIST_KEY, questionIds);
    }

    /**
     * 上一条数据
     * 
     * @param questionId
     * @return
     */
    public Long preQuestion(Long questionId) {
        long index = redisService.indexOfForList(CacheConstants.QUESTION_ID_LIST_KEY, questionId);
        if (index == 0) {
            throw new ServiceException(ResultCode.FIRST_QUESTION);
        }
        if (index < 0) {
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        return redisService.indexForList(CacheConstants.QUESTION_ID_LIST_KEY,
                index - 1, Long.class);
    }

    /**
     * 下一条数据
     */
    public Long nextQuestion(Long questionId) {
        long listSize = getListSize();
        long index = redisService.indexOfForList(CacheConstants.QUESTION_ID_LIST_KEY, questionId);
        if (index == listSize - 1) {
            throw new ServiceException(ResultCode.LAST_QUESTION);
        }
        if (index < 0) {
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        return redisService.indexForList(CacheConstants.QUESTION_ID_LIST_KEY,
                index + 1, Long.class);
    }

    /**
     * 得到热榜题目数据
     */
    public List<HotQuestionListVo> getHotQuestionList() {
        // 1. 先查询缓存
        List<HotQuestionListVo> cacheValue = redisService.getCacheListByRange(CacheConstants.HOT_QUESTION_LIST_KEY, 0,
                -1, HotQuestionListVo.class);
        if (cacheValue != null && !cacheValue.isEmpty()) {
            return cacheValue;
        }

        // 2. 检查是否存在空值标记
        Boolean hasEmptyMark = redisService.hasKey(CacheConstants.HOT_QUESTION_EMPTY_KEY);
        if (Boolean.TRUE.equals(hasEmptyMark)) {
            return null;
        }

        // 3. 缓存未命中且无空值标记，查询数据库
        // 从用户提交记录中统计提交次数最多的题目
        List<Long> hotQuestionIds = userSubmitMapper.selectHotQuestionIds(QuestionConstants.HOT_QUESTION_COUNT);
        if (hotQuestionIds == null || hotQuestionIds.isEmpty()) {
            // 4. 数据库查询为空，设置空值标记防止缓存击穿
            redisService.setCacheObject(CacheConstants.HOT_QUESTION_EMPTY_KEY, "",
                    CacheConstants.HOT_QUESTION_CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            return null;
        }

        // 5. 根据题目ID查询题目信息
        List<Question> questionList = questionMapper.selectBatchIds(hotQuestionIds);
        if (questionList == null || questionList.isEmpty()) {
            redisService.setCacheObject(CacheConstants.HOT_QUESTION_EMPTY_KEY, "",
                    CacheConstants.HOT_QUESTION_CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            return null;
        }

        // 6. 转换为VO并刷新缓存
        List<HotQuestionListVo> hotQuestionList = questionList.stream().map(question -> {
            HotQuestionListVo vo = new HotQuestionListVo();
            vo.setQuestionId(question.getQuestionId());
            vo.setTitle(question.getTitle());
            vo.setDifficulty(question.getDifficulty());
            // 获取该题目的提交次数
            Integer submitCount = userSubmitMapper.selectSubmitCountByQuestionId(question.getQuestionId());
            vo.setSubmitCount(submitCount != null ? submitCount : 0);
            return vo;
        }).toList();
        redisService.rightPushAll(CacheConstants.HOT_QUESTION_LIST_KEY, hotQuestionList);
        redisService.expire(CacheConstants.HOT_QUESTION_LIST_KEY, CacheConstants.HOT_QUESTION_CACHE_EXPIRE_TIME,
                TimeUnit.MINUTES);
        return hotQuestionList;
    }

}
